import React, { Component } from 'react';
import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
import ResizeObserver from 'resize-observer-polyfill';
import { themeLight, themeDark, commonConfig, gaugeConfig } from '../config';
import styles from '../index.less';

const { Arc } = Guide;
const { defaultTheme } = commonConfig;
const {
  defaultPointerFillColor,
  defaultArcWidth,
  defaultTitleFontSize,
  defaultGaugeDataFontSize,
} = gaugeConfig;

Shape.registerShape('point', 'pointer', {
  drawShape(cfg, group) {
    let point = cfg.points[0];
    point = this.parsePoint(point);
    const center = this.parsePoint({
      x: 0,
      y: 0,
    });
    group.addShape('line', {
      attrs: {
        x1: center.x,
        y1: center.y,
        x2: point.x,
        y2: point.y,
        stroke: cfg.color,
        lineWidth: 2 * window.viewportScale,
        lineCap: 'round',
      },
    });
    return group.addShape('circle', {
      attrs: {
        x: center.x,
        y: center.y,
        r: 6 * window.viewportScale,
        stroke: cfg.color,
        lineWidth: 3 * window.viewportScale,
        fill: defaultPointerFillColor,
      },
    });
  },
});

class Gauge extends Component {
  state = {
    height: 0,
    viewportScale: window.viewportScale,
  };

  componentDidMount() {
    this.resizeObserver();
    window.addEventListener('resize', this.resize, { passive: true });
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize);
  }

  handleRoot = n => {
    this.root = n;
  };

  resize = () => {
    this.setState({ viewportScale: window.viewportScale });
  };

  resizeObserver() {
    const ro = new ResizeObserver(entries => {
      const { width, height } = entries[0].contentRect;
      this.setState(preState => {
        if (preState.width !== width || preState.height !== height) {
          return {
            height,
          };
        }
        return null;
      });
    });
    if (this.root) {
      ro.observe(this.root);
    }
  }

  render() {
    const { height: stateHeight, viewportScale } = this.state;
    const { theme = defaultTheme } = this.props;
    const { defaultPointerColor, defaultArcColor, defaultTitleColor, defaultTotalColor } =
      theme === 'dark' ? themeDark : themeLight;
    const {
      style,
      height: propsHeight,
      forceFit = true,
      padding = 10 * viewportScale,
      percent,
      data = 0,
      pointerColor = defaultPointerColor,
      color = defaultArcColor,
      title,
      formatter,
    } = this.props;
    const cols = {
      value: {
        type: 'linear',
        min: 0,
        max: 10,
      },
    };

    const height = propsHeight || stateHeight;
    const chartData = [{ value: percent / 10 || data }];
    return (
      <div className={styles.gauge} ref={this.handleRoot} key={this.root}>
        <Chart
          style={style}
          height={height * viewportScale}
          data={chartData}
          scale={cols}
          padding={padding}
          forceFit={forceFit}
        >
          <Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={1} />
          <Axis name="1" line={null} />
          <Axis
            line={null}
            tickLine={null}
            subTickLine={null}
            name="value"
            zIndex={2}
            gird={null}
            label={null}
          />
          <Guide>
            {Array.from(new Array(10)).map((_val, i) => (
              <Arc
                key={i}
                zIndex={0}
                start={[i, 0.8]}
                end={[i + 1, 0.8]}
                style={{
                  stroke: color,
                  opacity: i / 10 + 0.1,
                  lineWidth: defaultArcWidth * viewportScale,
                }}
              />
            ))}
          </Guide>
          <Geom
            line={false}
            type="point"
            position="value*1"
            shape="pointer"
            color={pointerColor}
            active={false}
          />
        </Chart>
        <div className={styles.text}>
          <div style={{ fontSize: defaultTitleFontSize * viewportScale, color: defaultTitleColor }}>
            {title}
          </div>
          <div
            style={{ fontSize: defaultGaugeDataFontSize * viewportScale, color: defaultTotalColor }}
          >
            {percent !== undefined ? `${percent}%` : formatter ? formatter(data) : data}
          </div>
        </div>
      </div>
    );
  }
}

export default Gauge;
